/*
*
*
*     文档创建：jjl, jjl@hzncc.com
*/

#include <stdio.h>

#include <sys/types.h>
#include <sys/ioctl.h>
#include <net/if.h> 
#include <sys/socket.h> 
#include <unistd.h>
#include <sys/time.h> 
#include <fcntl.h>
#include <string.h>
#include <netpacket/packet.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>


//全局变量打包
struct ecats_vars{
	int 	sock_fd		;
	int 	recv_len	;		//接收的报文长度
	int		recv_done	;		//接收报文处理完毕，可以接收下一报文
	int		recv_err	;		//当没有处理完毕，接收下一报文，错误计数加一，丢弃新报文

};
static struct ecats_vars ecat;

//传入ethN网卡名称
int ecat_nic(char *eth)
{
	int ret;
	int i;
	int ifindex;
	struct timeval timeout;
	struct ifreq ifr;
   struct sockaddr_ll sll;
   	//使用原始套接字
   	ecat.sock_fd = socket(PF_PACKET, SOCK_RAW, htons(0x88a4));
	if(ecat.sock_fd < 0){
		perror("create sock:");
		return -1;
	}
	printf("interface :%s\n",eth);

	//设置收发的超时时间
	timeout.tv_sec =  0;
	timeout.tv_usec = 1; 
	ret = setsockopt(ecat.sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
	ret = setsockopt(ecat.sock_fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));

	i = 1;
	ret = setsockopt(ecat.sock_fd, SOL_SOCKET, SO_DONTROUTE, &i, sizeof(i));

	//通过名称绑定网卡
	strcpy(ifr.ifr_name, eth);
	ret = ioctl(ecat.sock_fd, SIOCGIFINDEX, &ifr);
	ifindex = ifr.ifr_ifindex;

	strcpy(ifr.ifr_name, eth);
	ifr.ifr_flags = 0;
	ret = ioctl(ecat.sock_fd, SIOCGIFFLAGS, &ifr);
	ifr.ifr_flags = ifr.ifr_flags | IFF_PROMISC | IFF_BROADCAST;
   	ret = ioctl(ecat.sock_fd, SIOCSIFFLAGS, &ifr);
	sll.sll_family = AF_PACKET;
	sll.sll_ifindex = ifindex;
	sll.sll_protocol = htons(0x88a4);
	ret = bind(ecat.sock_fd, (struct sockaddr *)&sll, sizeof(sll));
	if(ret){
		perror("bind:");
	}
	return ret;
}


unsigned char rcv_buffer[2048];
int main(int argc, char **argv)
{
	int ret;
	int cnt;
	int cnt_err;
	printf("ethmisc tool 2021.11.27\n");

	printf("ethercat interface : %s\n",argv[1]);
	if(ecat_nic(argv[1])){
		printf("ecat_nic error\n");
		return -1;
	}

	cnt = 0;
	cnt_err = 0;
	while(1){
		ret = recv(ecat.sock_fd, rcv_buffer, 2048, 0);
		if(ret > 0){
			cnt++;
			send(ecat.sock_fd, rcv_buffer, ret , 0);
		}else{
			cnt_err++;
		}

		if((cnt%10000) == 0){
			printf("cnt :%d cnt_err : %d\n",cnt,cnt_err);
		}

	}


	return 0;
}
